package eerbaar.server.statemachine;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Machine {

    private State current;

    private Transition currentTransition;

    private final List<State> states = new ArrayList<State>();

    private final List<Transition> transitions = new ArrayList<Transition>();

    public void addState(State state) {
        this.states.add(state);
    }

    public void addTransition(Transition transition) {
        this.transitions.add(transition);
    }

    public List<State> getStates() {
        return this.states;
    }

    public List<Transition> getTransitions() {
        return Collections.unmodifiableList(this.transitions);
    }

    public State lastState() {

        State result = null;
        if (this.states.size() > 0) {

            result = this.states.get(this.states.size() - 1);
        }

        return result;
    }

    private String list(List<Transition> list) {
        String s = "[";
        int index = 0;
        for (Transition t : list) {
            if (index > 0) {
                s += ", ";
            }
            s += t.string();
            index++;
        }
        s += "]";
        return s;
    }

    public void record(State inState) {

        State state = inState;

        if (this.current == null) {
            this.current = state;
            this.states.add(this.current);
            setupSimpleNames();
            return;
        }

        if (!this.states.contains(state)) {
            this.states.add(state);
            setupSimpleNames();
        } else {
            int index = this.states.indexOf(state);
            State existing = this.states.get(index);
            state = existing;
        }

        record(state, this.current);

        this.current = state;
    }

    private void record(State to, State from) {

        Transition transition = new Transition(to, from);
        record(transition);
    }

    private void record(Transition transition) {

        if (this.currentTransition == null) {
            this.currentTransition = transition;
            this.transitions.add(this.currentTransition);
            return;
        }

        if (this.currentTransition.equals(transition)) {
            this.currentTransition.incrementMultiplicity();
        }

        boolean found = false;
        for (Transition t : this.transitions) {
            if (t.equals(transition)) {
                t.incrementMultiplicity();
                found = true;
                break;
            }
        }
        if (!found) {
            this.transitions.add(transition);
        }

        this.currentTransition = transition;
    }

    private void setupSimpleNames() {

        final String s = "abcdefghijklmnopqrstvwxyz";
        int index = 0;

        for (State state : this.states) {
            state.setSimpleName("" + s.charAt(index));
            index++;
        }
    }

    private String simpleList(List<Transition> list) {
        String s = "[";
        int index = 0;
        for (Transition t : list) {
            if (index > 0) {
                s += ", ";
            }
            s += t.simpleString();
            index++;
        }
        s += "]";
        return s;
    }

    public State simpleState(String simpleWord) {

        State result = null;
        for (State state : this.states) {

            if (state.getSimpleName().equals(simpleWord)) {
                result = state;
                break;
            }
        }

        return result;
    }

    public String simpleString() {

        return this.simpleList(this.transitions);
    }

    public String string() {

        return this.list(this.transitions);
    }

    @Override
    public String toString() {
        String simple = this.simpleString();
        return "M" + simple;
        // return "Machine [\n current=" + this.current +
        // ",\n currentTransition="
        // + this.currentTransition + ",\n states=" + this.states
        // + ",\n transitions=" + this.transitions + ",\n transitions="
        // + simple + "\n]";
    }

}
